package org.tlipoca.smarticle.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jthinking.common.util.ip.IPInfo;
import com.jthinking.common.util.ip.IPInfoUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.genntii.smcommon.constant.ArticleStatusConstant;
import org.genntii.smcommon.constant.ExceptionConstant;
import org.genntii.smcommon.exception.*;
import org.genntii.smcommon.result.PageResult;
import org.genntii.smcommon.utils.AliOssUtil;
import org.genntii.smcommon.utils.DateUtil;
import org.genntii.smdomain.dto.ArticleItemDTO;
import org.genntii.smdomain.dto.ArticleTagRelationalDTO;
import org.genntii.smdomain.entity.Article;
import org.genntii.smdomain.entity.ArticleContent;
import org.genntii.smdomain.entity.ArticleTagRelational;
import org.genntii.smdomain.entity.Channel;
import org.genntii.smdomain.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.tlipoca.smarticle.client.*;
import org.tlipoca.smarticle.mapper.ArticleMapper;
import org.tlipoca.smarticle.service.ArticleService;
import org.tlipoca.smarticle.utils.IpUtil;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {

    @Resource
    private ArticleMapper articleMapper;

    @Resource
    private MongoTemplate mongoTemplate;

    @Resource
    private AliOssUtil aliOssUtil;

    @Resource
    private ChannelClient channelClient;

    @Resource
    private ArticleTagClient articleTagClient;

    @Resource
    private ArticleTagRelationalClient articleTagRelationalClient;

    @Resource
    private UserClient userClient;

    @Resource
    private ArticleLikeClient articleLikeClient;

    @Resource
    private UserSubScribeClient userSubScribeClient;

    @Resource
    private CommentClient commentClient;

    @Override
    public ArrayList<ArticleVO> getArticleVObyIds(ArrayList<Long> ids, Long userId) {
        ArrayList<Article> articles = articleMapper.getArticleListByIds(ids);

        Query query = new Query();
        query.addCriteria(Criteria.where("_id").in(ids.toArray(new Long[0])));
        List<ArticleContent> articleContents = mongoTemplate.find(query,ArticleContent.class);
        Map<Long, ArticleContent> articleContentMap = new HashMap<>();
        for (ArticleContent articleContent:articleContents){
            articleContentMap.put(articleContent.get_id(),articleContent);
        }
        ArrayList<ArticleVO> articleVOS = new ArrayList<>();
        for (Article article:articles){
            ArticleVO articleVO = new ArticleVO();
            articleVO.setId(article.getId());
            articleVO.setUserId(userId);
            articleVO.setChannelId(article.getChannelId());
            articleVO.setTitle(article.getTitle());
            articleVO.setCover(articleContentMap.get(article.getId()).getCover());
            articleVO.setContent(articleContentMap.get(article.getId()).getContent() );
            articleVO.setCreateTime(DateUtil.toString(article.getCreateTime()));
            articleVO.setUpdateTime(DateUtil.toString(article.getUpdateTime()));
            articleVO.setUserArticleCount(article.getUserArticleCount());
            articleVO.setUserFollowerCount(article.getUserFollowerCount());
            articleVO.setView(article.getView());
            articleVO.setLike(article.getLike());
            articleVO.setStatus(article.getStatus());
            articleVOS.add(articleVO);
        }
        return articleVOS;
    }

    @Override
    public ArrayList<ArticleVO> getArticleLimit(Long userId, Integer pageNum, Integer pageSize) {
        ArrayList<Article> articles = articleMapper.getArticleLimit(userId,(pageNum - 1) * pageSize, pageSize);
        List<Long> articleIds = new ArrayList<>();
        for (Article article : articles){
            articleIds.add(article.getId());
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").in(articleIds.toArray(new Long[0])));
        List<ArticleContent> articleContents = mongoTemplate.find(query,ArticleContent.class);
        Map<Long,ArticleContent> articleContentMap = new HashMap<>();
        for (ArticleContent articleContent:articleContents){
            articleContentMap.put(articleContent.get_id(),articleContent);
        }
        ArrayList<ArticleVO> articleVOS = new ArrayList<>();
        for (Article article:articles){
            ArticleVO articleVO = new ArticleVO();
            articleVO.setId(article.getId());
            articleVO.setUserId(userId);
            articleVO.setChannelId(article.getChannelId());
            articleVO.setTitle(article.getTitle());
            articleVO.setCover((articleContentMap.get(article.getId()).getCover()!=null)?articleContentMap.get(article.getId()).getCover():new ArrayList<>());
            articleVO.setContent(articleContentMap.get(article.getId()).getContent() );
            articleVO.setCreateTime(DateUtil.toString(article.getCreateTime()));
            articleVO.setUpdateTime(DateUtil.toString(article.getUpdateTime()));
            articleVO.setUserArticleCount(article.getUserArticleCount());
            articleVO.setUserFollowerCount(article.getUserFollowerCount());
            articleVO.setView(article.getView());
            articleVO.setLike(article.getLike());
            articleVO.setStatus(article.getStatus());
            articleVOS.add(articleVO);
        }
        return articleVOS;
    }

    @Override
    public void setFollower(Integer follower, Long userId) {
        articleMapper.userFollowerCountUpdate(follower, userId);
    }

    @Override
    public ArrayList<ArticleVO> getArticleByUserId(Long userId) {
        ArrayList<Article> articles = articleMapper.selectArticleByUserId(userId);
        ArrayList<ArticleVO> articleVOS = new ArrayList<>();
        for (Article article : articles){
            articleVOS.add(ArticleVO.builder()
                    .id(article.getId())
                    .userId(article.getUserId())
                    .channelId(article.getChannelId())
                    .title(article.getTitle())
                    .like(article.getLike())
                    .status(article.getStatus())
                    .view(article.getView())
                    .userArticleCount(article.getUserArticleCount())
                    .userFollowerCount(article.getUserFollowerCount())
                    .build());
        }
        return articleVOS;
    }

    @Override
    public ArrayList<ArticleVO> getArticleByChannelD(Integer pageNum, Integer pageSize, Long channelId, String keyword, LocalDateTime latestUpdateTime, Byte type,Byte subscribe) {
        ArrayList<Article> articles = switch (type) {
            case 0 ->//new
                    articleMapper.getArticleListNew(channelId, keyword, latestUpdateTime, (pageNum - 1) * pageSize, pageSize);
            case 1, 2 ->//hot
                    articleMapper.getArticleListHot(channelId, keyword, latestUpdateTime, (pageNum - 1) * pageSize, pageSize);
            default -> throw new ParamErrorException(ExceptionConstant.PARAM_ERROR_EXCEPTION);
        };
        ArrayList<ArticleVO> articleVOS = new ArrayList<>();
        HashMap<Long, ArticleContent> articleContentHashMap = new HashMap<>();
        ArrayList<Long> articleIds = new ArrayList<>();
        for (Article article : articles){
            articleIds.add(article.getId());
            articleContentHashMap.put(article.getId(),mongoTemplate.findOne(new Query(Criteria.where("_id").is(article.getId())),ArticleContent.class));
        }
        Map<String, ArrayList<ArticleTagVO>> articleTagMap =
                articleTagClient.getArticleTagListByArticleTagMap
                        (articleTagRelationalClient.getTagIdsByArticleIds(articleIds).getData()).getData();
        for (Article article:articles){
            LikeVO articleLikeVO = articleLikeClient.getArticleLike(article.getId(),article.getUserId()).getData();
            UserVO userVO = userClient.getUserById(article.getUserId()).getData();
            articleVOS.add(ArticleVO.builder()
                    .id(article.getId())
                    .userId(article.getUserId())
                    .userName(userVO.getNickname())
                    .avatar(userVO.getAvatar())
                    .channelId(channelId)
                    .title(article.getTitle())
                    .status(article.getStatus())
                    .createTime(DateUtil.toString(article.getCreateTime()))
                    .updateTime(DateUtil.toString(article.getUpdateTime()))
                    .view(article.getView())
                    .userArticleCount(articleMapper.getUserArticleCount(article.getUserId()))
                    .content(articleContentHashMap.get(article.getId()).getContent())
                    .cover(articleContentHashMap.get(article.getId()).getCover())
                    .articleTags(articleTagMap.get(String.valueOf(article.getId())))
                    .userFollowerCount(article.getUserFollowerCount())
                    .like(articleLikeVO.getLike())
                    .commentCount(commentClient.getCommentCount(article.getId()).getData())
                    .build());
        }
        return articleVOS;
    }

    @Override
    public ArrayList<ArticleVO> getArticleByChannel(Integer pageNum, Integer pageSize, Long channelId) {
        ArrayList<Article> articles = articleMapper.getArticleByChannel(channelId,(pageNum-1)*pageSize,pageSize);
        ArrayList<ArticleVO> articleVOS = new ArrayList<>();
        HashMap<Long, ArticleContent> articleContentHashMap = new HashMap<>();
        ArrayList<Long> articleIds = new ArrayList<>();
        for (Article article : articles){
            articleIds.add(article.getId());
            articleContentHashMap.put(article.getId(),mongoTemplate.findOne(new Query(Criteria.where("_id").is(article.getId())),ArticleContent.class));
        }
        Map<String, ArrayList<ArticleTagVO>> articleTagMap =
                articleTagClient.getArticleTagListByArticleTagMap
                        (articleTagRelationalClient.getTagIdsByArticleIds(articleIds).getData()).getData();
        for (Article article : articles){
            UserVO userVO = userClient.getUserById(article.getUserId()).getData();
            LikeVO articleLikeVO = articleLikeClient.getArticleLike(article.getId(),article.getUserId()).getData();
            articleVOS.add(ArticleVO.builder()
                    .id(article.getId())
                    .userId(article.getUserId())
                    .userName(userVO.getNickname())
                    .avatar(userVO.getAvatar())
                    .channelId(channelId)
                    .title(article.getTitle())
                    .content(articleContentHashMap.get(article.getId()).getContent())
                    .cover(articleContentHashMap.get(article.getId()).getCover())
                    .status(article.getStatus())
                    .articleTags(articleTagMap.get(String.valueOf(article.getId())))
                    .view(article.getView())
                    .userArticleCount(articleMapper.getUserArticleCount(article.getUserId()))
                    .createTime(DateUtil.toString(article.getCreateTime()))
                    .updateTime(DateUtil.toString(article.getUpdateTime()))
                    .userFollowerCount(article.getUserFollowerCount())
                    .like(articleLikeVO.getLike())
                    .commentCount(commentClient.getCommentCount(article.getId()).getData())
                    .build());
        }
        return articleVOS;
    }

    @Override
    public PageResult<ArticleVO> getLatestArticle(Integer pageNum, Integer pageSize, Integer order, Integer subscribeFilter, Long userId) {
        ArrayList<UserSubScribeClientVO> userSubscribes = new ArrayList<>();
        switch (subscribeFilter){
            case 1:
                userSubscribes = userSubScribeClient.subscribe8u(userId).getData();
                break;
            case 2:
                userSubscribes = userSubScribeClient.subscribe8c(userId).getData();
                break;
            case 0:
                break;
        }
        ArrayList<Long> ids = new ArrayList<>();
        for (UserSubScribeClientVO userSubscribe:userSubscribes){
            if (subscribeFilter == 2) ids.add(userSubscribe.getChannelId());
            else if (subscribeFilter == 1) {
               ids.add(userSubscribe.getSubscriberUserId());
            }else {
                if (userSubscribe.getChannelId()!=0) ids.add(userSubscribe.getChannelId());
                if (userSubscribe.getSubscriberUserId() != 0) ids.add(userSubscribe.getSubscriberUserId());
            }
        }

        ArrayList<Article> articleList = articleMapper.getLatestArticle((pageNum-1)*pageSize, pageSize,order,subscribeFilter,ids);
        List<Long> articleIds = new ArrayList<>();
        for (Article article : articleList){
            articleIds.add(article.getId());
        }
        ArrayList<ArticleVO> voList = new ArrayList<>();
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").in(articleIds.toArray(new Long[0])));
        List<ArticleContent> articleContents = mongoTemplate.find(query,ArticleContent.class);
        Map<Long,ArticleContent> articleContentMap = new HashMap<>();
        for (ArticleContent articleContent:articleContents){
            articleContentMap.put(articleContent.get_id(),articleContent);
        }
        for (Article article: articleList){
//            UserVO userVO = userClient.getUserById(article.getUserId()).getData();
            LikeVO articleLikeVO = articleLikeClient.getArticleLike(article.getId(),article.getUserId()).getData();
            ArticleVO vo = ArticleVO.builder()
                    .id(article.getId())
//                    .userId(article.getUserId())
                    .userName(userClient.getUserById(article.getUserId()).getData().getNickname())
//                    .avatar(userVO.getAvatar())
//                    .channelId(article.getChannelId())
                    .title(article.getTitle())
                    .content(articleContentMap.get(article.getId()).getContent())
                    .cover(articleContentMap.get(article.getId()).getCover())
//                    .status(article.getStatus())
                    .createTime(DateUtil.toString(article.getCreateTime()))
                    .updateTime(DateUtil.toString(article.getUpdateTime()))
//                    .userArticleCount(articleMapper.getUserArticleCount(article.getUserId()))
                    .view(article.getView())
//                    .userFollowerCount(article.getUserFollowerCount())
                    .like(article.getLike())
                    .commentCount(commentClient.getCommentCount(article.getId()).getData())
                    .build();
            voList.add(vo);
        }
        return PageResult.build(voList,articleMapper.getLatestArticleTotal(ids,subscribeFilter));
    }

    @Override
    public Boolean articleExistsService(Long articleId) {
        return articleMapper.selectArticle(articleId)!=null;
    }

    @Override
    public void addArticleService(ArticleItemDTO articleItemDTO,String ipv4,Long userId) {
        // 查询文章标签是否存在
        if (!articleTagClient.articleTagListExists(articleItemDTO.getArticleTagId()).getData()) {
            log.info("文章标签不存在");
            throw new ArticleTagNotFoundException(ExceptionConstant.ARTICLE_TAG_NOT_FOUND_EXCEPTION);
        }



        // 查询频道是否存在
        if (!channelClient.channelExists(articleItemDTO.getChannelId()).getData()) {
            log.info("频道不存在");
            throw new ChannelNotFoundException(ExceptionConstant.CHANNEL_NOT_FOUND_EXCEPTION);
        }

        // 更新Mysql文章表
        Article article = new Article();
        article.setCreateTime(LocalDateTime.now());
        article.setUpdateTime(LocalDateTime.now());
        article.setLike(0);
        article.setDislike(0);
        if (!ipv4.equals(IpUtil.LOCAL_IP)){
            IPInfo ip = IPInfoUtils.getIpInfo(ipv4);
            article.setCity(ip.getProvince().isEmpty() ?ip.getProvince():ip.getCountry());
        }else article.setCity("测试环境");
        articleItemDTO.setUserId(userId);

        BeanUtils.copyProperties(articleItemDTO, article);
        article.setStatus((byte) 1);
        log.info("Mysql新增文章");
        articleMapper.insertGetId(article);

        // 插入文章标签
        articleTagRelationalClient.addArticleTagRelational(
                ArticleTagRelationalDTO.builder()
                        .articleId(article.getId())
                        .tagIds(articleItemDTO.getArticleTagId())
                        .build());

        // 更新MongoDB
        ArticleContent articleContent = ArticleContent.builder()
                ._id(article.getId())
                .title(articleItemDTO.getTitle())
                .content(articleItemDTO.getContent())
                .cover(articleItemDTO.getCover())
                .build();
        log.info("MongoDB新增文章");
        mongoTemplate.insert(articleContent);

        articleMapper.userFollowerCountUpdate(userSubScribeClient.getSubscribeNum(article.getUserId()).getData().getSubscribedNum(),article.getUserId());
        // 调用RabbitMQ
        // TODO. 异步更新Mysql文章标签中间表

    }

    @Override
    public void deleteArticleService(Long articleId) {
        // 查询文章是否存在
        if (!articleMapper.exists(new QueryWrapper<Article>().eq("id", articleId))) {
            log.info("文章 {} 不存在", articleId);
            throw new ArticleNotFoundException(ExceptionConstant.ARTICLE_NOT_FOUND_EXCEPTION);
        }

        // 删除Mysql
        log.info("删除Mysql 文章id: {}", articleId);
        articleMapper.deleteById(articleId);

        // 删除MongoDB
        log.info("删除MongoDB 文章id: {}", articleId);
        mongoTemplate.remove(new Query(Criteria.where("_id").is(articleId)),ArticleContent.class);
    }

    @Override
    public void updateArticleStatusService(Long articleId, Integer status) {
        // 判断文章是否存在
        Article article = articleMapper.selectArticle(articleId);
        if (article == null) {
            log.info("文章 {} 不存在", articleId);
            throw new ArticleNotFoundException(ExceptionConstant.ARTICLE_NOT_FOUND_EXCEPTION);
        }

        // 判断文章是否已经为该状态
        if (article.getStatus() == status) {
            throw new ArticleAlreadyStatusException(ExceptionConstant.ARTICLE_ALREADY_STATUS_EXCEPTION);
        }

        // 更新文章状态
        articleMapper.updateArticleStatus(articleId, status);
    }

    @Override
    public void updateArticleService(Long articleId, ArticleItemDTO articleItemDTO) {
        Article article = new Article();
        BeanUtils.copyProperties(articleItemDTO, article, "articleTagId");
        article.setId(articleId);

        Article articleResult = articleMapper.selectArticle(articleId);
        if (articleResult == null) {
            log.info("文章 {} 不存在", articleId);
            throw new ArticleNotFoundException(ExceptionConstant.ARTICLE_NOT_FOUND_EXCEPTION);
        }

        // 若修改文章标签 查询文章标签是否存在
        if (articleItemDTO.getArticleTagId() != null) {
            if (!articleTagClient.articleTagListExists(articleItemDTO.getArticleTagId()).getData()) {
                log.info("文章标签不存在");
                throw new ArticleTagNotFoundException(ExceptionConstant.ARTICLE_TAG_NOT_FOUND_EXCEPTION);
            }

            // TODO. 异步更新文章标签
        }

        // 若修改频道 查询频道是否存在
        if (articleItemDTO.getChannelId() != null) {
            if (!channelClient.channelExists(articleItemDTO.getChannelId()).getData()) {
                log.info("频道不存在");
                throw new ChannelNotFoundException(ExceptionConstant.CHANNEL_NOT_FOUND_EXCEPTION);
            }

            // 更新实体类频道
            article.setChannelId(articleItemDTO.getChannelId());
        }

        // 更新Mysql
        articleMapper.update(article, new QueryWrapper<Article>().eq("id", articleId));

        // 若标题或文章内容更新则更新MongoDB
        if (articleItemDTO.getContent() != null || articleItemDTO.getTitle() != null || articleItemDTO.getCover() != null && !articleItemDTO.getCover().isEmpty()) {
            Update update = new Update();

            if (articleItemDTO.getContent() != null) update.set("content", articleItemDTO.getContent());

            if (articleItemDTO.getTitle() != null) update.set("title", articleItemDTO.getTitle());

            if (articleItemDTO.getCover() != null && !articleItemDTO.getCover().isEmpty())
                update.set("cover", articleItemDTO.getCover());

            mongoTemplate.upsert(new Query(Criteria.where("_id").is(articleId)), update, ArticleContent.class);
        }
    }

    @Override
    public ArticleDetailVO getArticleByIdService(Long articleId, Long userId) {
        // 判断文章是否存在
        Article article = articleMapper.selectArticle(articleId);
        if (article == null) {
            log.info("文章 {} 不存在", articleId);
            throw new ArticleNotFoundException(ExceptionConstant.ARTICLE_NOT_FOUND_EXCEPTION);
        }

        // 判断文章是否可见
        if (article.getStatus() == ArticleStatusConstant.ARTICLE_HIDDEN) {
            log.info("文章 {} 不可见", articleId);
            throw new ArticleHiddenException(ExceptionConstant.ARTICLE_HIDDEN_EXCEPTION);
        }

        UserVO userVO = userClient.getUserById(article.getUserId()).getData();
        LikeVO articleLikeVO = articleLikeClient.getArticleLike(articleId,userId).getData();
        ChannelVO channel = channelClient.getChannelById(article.getChannelId(),userId).getData();
        ArticleDetailVO articleDetailVO = ArticleDetailVO.builder()
                .id(article.getId())
                .userId(article.getUserId())
                .authorName(userVO.getNickname())
                .avatar(userVO.getAvatar())
                .channelId(article.getChannelId())
                .channelName(channel.getChannelName())
                .title(article.getTitle())
//                .like(articleLikeVO.getLike())
//                .dislike(articleLikeVO.getDislike())
//                .liked(articleLikeVO.getLiked())
                .cityCode(article.getCityCode())
                .cityName(article.getCity())
                .status(article.getStatus())
                .createTime(DateUtil.toString(article.getCreateTime()))
                .updateTime(DateUtil.toString(article.getUpdateTime()))
                .userArticleCount(articleMapper.getUserArticleCount(userVO.getId()))
                .view(article.getView())
                .userFollowerCount(article.getUserFollowerCount())
                .icon(channel.getChannelIcon())
                .subscribed(userSubScribeClient.userSubscribed((byte) 2,article.getUserId(),userId).getData())
                .build();
        if (articleLikeVO != null){
            articleDetailVO.setLike(articleLikeVO.getLike());
            articleDetailVO.setDislike(articleLikeVO.getDislike());
            articleDetailVO.setLiked(articleLikeVO.getLiked());
        }
        // 查询tag
        ArrayList<ArticleTagRelational> a = articleTagRelationalClient.getArticleTagRelationalByArticleId(articleId).getData();
        // 获取tagIds
        ArrayList<Long> tagIds = new ArrayList<>();
        for (ArticleTagRelational articleTagRelational : a){
            tagIds.add(articleTagRelational.getTagId());
        }
        articleDetailVO.setArticleTags(articleTagClient.getArticleTagListByTagId(tagIds).getData());

        // 查询MongoDB 获取文章内容 封面
        ArticleContent articleContent = mongoTemplate.findOne(new Query(Criteria.where("_id").is(articleId)), ArticleContent.class);
        articleDetailVO.setContent(articleContent.getContent());
        articleDetailVO.setCover(articleContent.getCover());

        UserVO author = userClient.getUserById(article.getUserId()).getData();
        articleDetailVO.setAuthorName((author.getNickname() == null || author.getNickname().isEmpty()) ? author.getUsername() : author.getNickname());
        articleDetailVO.setAvatar(author.getAvatar());


//        Channel channel = channelClient.getChannelById(article.getChannelId(), userId).getData();
//        articleDetailVO.setChannelName(channel.getChannelName());

        articleMapper.viewCountPlus1(articleId);

        return articleDetailVO;
    }

    @Override
    public ArrayList<ArticleDetailVO> getArticleListByIdsService(ArrayList<Long> articleIds,Long userId1) {

        ArrayList<ArticleDetailVO> articleDetailVOList = new ArrayList<>();
        ArrayList<Article> articleList = articleMapper.getArticleListByIds(articleIds);
        ArrayList<Long> userIdList = new ArrayList<>();
        ArrayList<Long> channelIdList = new ArrayList<>();
        Map<Long, Article> articleMap = new HashMap<>();
        Map<Long, ArticleContent> articleDetailMap = new HashMap<>();

        for (Article article : articleList) {
            System.out.println(article.getCity());
            articleMap.put(article.getId(), article);
            userIdList.add(article.getUserId());
            channelIdList.add(article.getChannelId());
        }

        Map<String, ArrayList<ArticleTagVO>> articleTagMap = articleTagClient.getArticleTagListByArticleTagMap(articleTagRelationalClient.getTagIdsByArticleIds(articleIds).getData()).getData();
        Map<Long, UserVO> userListMap = userClient.getUserListMapByIds(userIdList).getData();
        Map<Long, ChannelVO> channelMap = channelClient.getChannelListByIds(channelIdList,userId1).getData();

        List<ArticleContent> articleDetailList = mongoTemplate.find(new Query(Criteria.where("_id").in(articleIds)), ArticleContent.class);
        for (ArticleContent articleDetail : articleDetailList) {
            articleDetailMap.put(articleDetail.get_id(), articleDetail);
        }


        for (Long id : articleIds) {
            Long userId = articleMap.get(id).getUserId();
            Long channelId = articleMap.get(id).getChannelId();
            LikeVO articleLikeVO = articleLikeClient.getArticleLike(id,userId).getData();
            ArticleDetailVO detailVO = ArticleDetailVO.builder()
                    .id(id)
                    .userId(userId)
                    .authorName((userListMap.get(userId).getNickname() == null || userListMap.get(userId).getNickname().isEmpty()) ? userListMap.get(userId).getUsername() : userListMap.get(userId).getNickname())
                    .channelId(articleMap.get(id).getChannelId())
                    .channelName(channelMap.get(channelId).getChannelName())
                    .title(articleMap.get(id).getTitle())
                    .content(articleDetailMap.get(id).getContent())
                    .like(articleMap.get(id).getLike())
                    .dislike(articleMap.get(id).getDislike())
                    .cityName(articleMap.get(id).getCity())
                    .status(articleMap.get(id).getStatus())
                    .articleTags(articleTagMap.get(String.valueOf(id)))
                    .createTime(DateUtil.toString(articleMap.get(id).getCreateTime()))
                    .updateTime(DateUtil.toString(articleMap.get(id).getUpdateTime()))
                    .userArticleCount(articleMapper.getUserArticleCount(userId))
                    .view(articleMap.get(id).getView())
                    .userFollowerCount(articleMap.get(id).getUserFollowerCount())
                    .like(articleLikeVO.getLike())
                    .dislike(articleLikeVO.getDislike())
                    .liked(articleLikeVO.getLiked())
                    .build();

            if (articleDetailMap.get(id).getCover() != null){
                detailVO.setCover(articleDetailMap.get(id).getCover());
            }
            articleDetailVOList.add(detailVO);
        }

        return articleDetailVOList;
    }


    @Override
    public ArrayList<ArticleVO> articleList(ArrayList<Long> ids) {
        ArrayList<ArticleVO> articleVOList = new ArrayList<>();
        ArrayList<Article> articleList = articleMapper.getArticleListByIds(ids);
        Map<Long, Article> articleMap = new HashMap<>();
        Map<Long, ArticleContent> articleDetailMap = new HashMap<>();

        for (Article article : articleList) {
            System.out.println(article.getCity());
            articleMap.put(article.getId(), article);
        }

        Map<String, ArrayList<ArticleTagVO>> articleTagMap = articleTagClient.getArticleTagListByArticleTagMap(articleTagRelationalClient.getTagIdsByArticleIds(ids).getData()).getData();

        List<ArticleContent> articleDetailList = mongoTemplate.find(new Query(Criteria.where("_id").in(ids)), ArticleContent.class);
        for (ArticleContent articleDetail : articleDetailList) {
            articleDetailMap.put(articleDetail.get_id(), articleDetail);
        }


        for (Long id : ids) {
            Long userId = articleMap.get(id).getUserId();
            LikeVO articleLikeVO = articleLikeClient.getArticleLike(id,userId).getData();
            ArticleVO VO = ArticleVO.builder()
                    .id(id)
                    .userId(userId)
                    .userName(userClient.getUserById(userId).getData().getNickname())
                    .channelId(articleMap.get(id).getChannelId())
                    .title(articleMap.get(id).getTitle())
                    .content(articleDetailMap.get(id).getContent())
                    .status(articleMap.get(id).getStatus())
                    .articleTags(articleTagMap.get(String.valueOf(id)))
                    .createTime(DateUtil.toString(articleMap.get(id).getCreateTime()))
                    .updateTime(DateUtil.toString(articleMap.get(id).getUpdateTime()))
                    .userArticleCount(articleMapper.getUserArticleCount(userId))
                    .view(articleMap.get(id).getView())
                    .userFollowerCount(articleMap.get(id).getUserFollowerCount())
                    .like(articleLikeVO.getLike())
                    .commentCount(commentClient.getCommentCount(id).getData())
                    .build();

            if (articleDetailMap.get(id).getCover() != null){
                VO.setCover(articleDetailMap.get(id).getCover());
            }
            articleVOList.add(VO);
        }

        return articleVOList;
    }

    @Override
    public void articleLikeUpdate(int like, int dislike, Long articleId) {
        Article article = articleMapper.selectArticle(articleId);
        if (article == null) {
            log.info("文章 {} 不存在", articleId);
            throw new ArticleNotFoundException(ExceptionConstant.ARTICLE_NOT_FOUND_EXCEPTION);
        }
        articleMapper.ArticleLikeUpdate(like,dislike,articleId);
    }

    @Override
    public Map<Integer, String> BatchUpload(MultipartFile[] files) {
        Map<Integer, String> urls = new HashMap<>();
        List<MultipartFile> fileList = Arrays.asList(files);
        for (MultipartFile file:fileList){
            try {
                urls.put(fileList.indexOf(file), aliOssUtil.upload(file.getBytes(), file.getOriginalFilename()));
            } catch (IOException e){
                throw new RuntimeException(e+"上传失败");
            }
        }
        return urls;
    }
    @Override
    public Long getTotalUserArticleByUserId(Long userId){
        return articleMapper.getArticleTotalByUser(userId);
    }

    @Override
    public void setLike(Integer like, Integer dislike, Long articleId) {
        articleMapper.setLike(like,dislike,articleId);
    }
}
